using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EcsManager
{
    public static int LogicFrame = 20;
    public static bool AllowLogicFrameLoop;
    public static bool AllowInputFrameLoop;

    
    public static Contexts EcsContexts => Contexts.sharedInstance;
    static LogicSystems mLogicSystems;
    static InputSystems mInputSystems;
    
    static float mAcceleratorLogicFrameTime;

    public static Transform EcsRoot;
    public static Transform GridRoot;
    public static Transform CellRoot;
    
    public static void Init()
    {
        mLogicSystems = new LogicSystems(EcsContexts.logic); 
        mLogicSystems.Initialize();
        mInputSystems = new InputSystems(EcsContexts.input);
        mInputSystems.Initialize();
        AllowLogicFrameLoop = false;
        AllowInputFrameLoop = false;
        mAcceleratorLogicFrameTime = 0f;

        PreCreateEntity(500);
        InitRootObj();
    }

    static List<LogicEntity> mTempEntityPool = new List<LogicEntity>(500);

    public static void PreCreateEntity(int count)
    {
        mTempEntityPool.Clear();
        for (int i = 0; i < count; i++)
        {
            LogicEntity e = EcsContexts.logic.CreateEntity();
            mTempEntityPool.Add(e);
        }
        mLogicSystems.Execute();
        mLogicSystems.Cleanup();
        foreach (var e in mTempEntityPool)
            e.isDestroy = true;
        mLogicSystems.Execute();
        mLogicSystems.Cleanup();
    }
    
    public static void InitRootObj()
    {
        EcsRoot = new GameObject("EcsRoot").transform;
        GridRoot = new GameObject("GridRoot").transform;
        CellRoot = new GameObject("CellRoot").transform;
        
        GridRoot.SetParent(EcsRoot);
        CellRoot.SetParent(EcsRoot);
        
        GameObject.DontDestroyOnLoad(EcsRoot);
    }

    public static void Dispose()
    {
        mLogicSystems = null;
        AllowLogicFrameLoop = false;
        mAcceleratorLogicFrameTime = 0f;
    }

    public static void Update()
    {
        if (AllowInputFrameLoop)
            InputFrameLoop();
        if (AllowLogicFrameLoop)
            LogicFrameLoop();
    }

    static void LogicFrameLoop()
    {
        if (Time.timeScale <= 0f || LogicFrame <= 0) return;
        float deltaTime = Time.deltaTime;
        float perLogicFrameTime = 1f / LogicFrame;
        mAcceleratorLogicFrameTime += deltaTime;

        while (mAcceleratorLogicFrameTime > perLogicFrameTime)
        {
            mLogicSystems.Execute();
            mLogicSystems.Cleanup();
            mAcceleratorLogicFrameTime -= perLogicFrameTime;
        }
    }
    
    static void InputFrameLoop()
    {
        mInputSystems.Execute();
        mInputSystems.Cleanup();
    }
}
